import deviceManager from '@ohos.distributedHardware.deviceManager';

const TAG: string = 'BT_Demo[RemoteDeviceModel]'

let SUBSCRIBE_ID = 100;

export default class RemoteDeviceModel {
    deviceList = []
    discoverList = []
    deviceManagerInst = undefined
    discoverErrorString: string = null

    registerDeviceListCallback(bundleName: string, callback: (string) => void) {
        console.info(`${TAG} registerDeviceListCallback`);
        if (this.deviceManagerInst === undefined) {
            console.log(`${TAG} deviceManager.createDeviceManager`);
            deviceManager.createDeviceManager(bundleName, (error, value) => {
                if (error) {
                    console.error(`${TAG} createDeviceManager failed.`);
                    return;
                }
                this.deviceManagerInst = value;
                console.log(`${TAG} createDeviceManager callback returned, value=` + value);
                this.registerDeviceListCallback_(callback);
            });
            console.log(`${TAG} deviceManager.createDeviceManager end`);
        } else {
            this.registerDeviceListCallback_(callback);
        }
    }

    registerDeviceListCallback_(callback: (string) => void) {
        console.info(`${TAG} registerDeviceListCallback_`);
        if (this.deviceManagerInst === undefined) {
            console.error(`${TAG} deviceManager has not initialized`);
            callback('Initialized error');
            return;
        }

        console.info(`${TAG} getTrustedDeviceListSync begin`);
        let list = this.deviceManagerInst.getTrustedDeviceListSync();
        console.log(`${TAG} getTrustedDeviceListSync end, deviceList=` + JSON.stringify(list));
        if (list !== undefined && list.length !== undefined) {
            this.deviceList = list;
        }
        callback(null);
        console.info(`${TAG} callback finished`);

        this.discoverErrorString = null
        this.deviceManagerInst.on('deviceStateChange', (data) => {
            console.log(`${TAG} deviceStateChange data=` + JSON.stringify(data));
            switch (data.action) {
                case deviceManager.DeviceStateChangeAction.READY:
                    this.discoverList = []
                    this.deviceList.push(data.device)
                    console.log(`${TAG} ready, updated device list=` + JSON.stringify(this.deviceList));
                    let list = this.deviceManagerInst.getTrustedDeviceListSync();
                    if (list !== undefined && list.length !== undefined) {
                        this.deviceList = list;
                    }
                    console.log(`${TAG} getTrustedDeviceListSync end, deviceList=` + JSON.stringify(list));
                    callback(null);
                    break;
                case deviceManager.DeviceStateChangeAction.OFFLINE:
                    if (this.deviceList.length > 0) {
                        let list = [];
                        for (let j = 0; j < this.deviceList.length; j++) {
                            if (this.deviceList[j].deviceId !== data.device.deviceId) {
                                list[j] = data.device;
                            }
                        }
                        this.deviceList = list;
                    }
                    console.log(`${TAG} offline, updated device list=` + JSON.stringify(data.device));
                    callback(null);
                    break;
                default:
                    break;
            }
        });
        this.deviceManagerInst.on('deviceFound', (data) => {
            console.log(`${TAG} deviceFound data=` + JSON.stringify(data));
            for (let i = 0;i < this.discoverList.length; i++) {
                if (this.discoverList[i].deviceId === data.device.deviceId) {
                    console.info(`${TAG} device ${data.device.deviceName} already found`);
                    return;
                }
            }
            this.discoverList[this.discoverList.length] = data.device;
            console.log(`${TAG} deviceFound this.discoverList=` + JSON.stringify(this.discoverList));
            callback(null);
        });
        this.deviceManagerInst.on('discoverFail', (data) => {
            this.discoverErrorString = 'discoverFail reason=' + data.reason
            console.log(`${TAG} discoverFail data=` + JSON.stringify(data));
        });
        this.deviceManagerInst.on('serviceDie', () => {
            console.error(`${TAG} serviceDie`);
            callback('serviceDie')
        });

        SUBSCRIBE_ID = Math.floor(65536 * Math.random());
        let info = {
            subscribeId: SUBSCRIBE_ID,
            mode: 0xAA,
            medium: 2,
            freq: 2,
            isSameAccount: false,
            isWakeRemote: true,
            capability: 0
        };
        console.log(`${TAG} startDeviceDiscovery ` + SUBSCRIBE_ID);
        try {
            this.deviceManagerInst.startDeviceDiscovery(info);
        } catch (err) {
            console.error(`${TAG} startDeviceDiscovery ` + JSON.stringify(err));
            if (this.discoverErrorString == null) {
                this.discoverErrorString = `startDeviceDiscovery ` + JSON.stringify(err)
            }
        }

        setTimeout(() => { // to wait Discovering result on flag discoverErrorString (on('discoverFail'...)
            console.info(`${TAG} callback finished err=${this.discoverErrorString}`);
            callback(this.discoverErrorString);
        }, 200)
    }

    unregisterDeviceListCallback() {
        console.log(`${TAG} stopDeviceDiscovery ` + SUBSCRIBE_ID);
        if (this.deviceManagerInst === undefined) {
            return
        }
        try {
            this.deviceManagerInst.stopDeviceDiscovery(SUBSCRIBE_ID);
        } catch(err) {
            console.error(`${TAG} stopDeviceDiscovery ` + JSON.stringify(err))
        }
        this.deviceManagerInst.off('deviceStateChange');
        this.deviceManagerInst.off('deviceFound');
        this.deviceManagerInst.off('discoverFail');
        this.deviceManagerInst.off('serviceDie');
        this.deviceList = [];
        this.deviceManagerInst = undefined
    }

    authenticateDevice(device, bundleName: string, appName: string, callBack) {
        console.log(`${TAG} authenticateDevice ` + JSON.stringify(device));
        for (let i = 0; i < this.discoverList.length; i++) {
            if (this.discoverList[i].deviceId === device.deviceId) {
                let extraInfo = {
                    'targetPkgName': bundleName,
                    'appName': appName,
                    'appDescription': appName,
                    'business': '0'
                };
                let authParam = {
                    'authType': 1,
                    'extraInfo': extraInfo
                };
                if (this.deviceManagerInst === undefined) {
                    return
                }
                this.deviceManagerInst.authenticateDevice(device, authParam, (err, data) => {
                    if (err) {
                        console.error(`${TAG} authenticateDevice error:` + JSON.stringify(err));
                        callBack(true)
                        return;
                    }
                    console.log(`${TAG} authenticateDevice succeed:` + JSON.stringify(data));
                    callBack(false)
                })
            }
        }
    }
}
